#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <stdlib.h>
#include <iostream>

#include "../main.cpp"

using namespace std;

static SDL_Cursor *cursor();
SDL_Surface *boardImg=0, *black=0, *white=0, *threat=0, *available=0, *considerable=0, *screen=0;
SDL_Rect boardRect = {0,0,376,376};
SDL_Rect blockRect = {0,0,24,24};

void drawBoard() {
    if( SDL_BlitSurface(boardImg, 0, SDL_GetVideoSurface(), &boardRect) )
        cerr<<"WTF!"<<endl;
    SDL_UpdateRect( screen, 0,0, 376, 376 );
}
void drawPiece(char who, int x, int y) {
    blockRect.x = x*25;
    blockRect.y = y*25;
    switch(who) {
    case O:
        SDL_BlitSurface(black, 0, screen, &blockRect);
        break;
    case X:
        SDL_BlitSurface(white, 0, screen, &blockRect);
        break;
    case '.':
        SDL_BlitSurface(threat, 0, screen, &blockRect);
        break;
    case 'a':
        SDL_BlitSurface(available, 0, screen, &blockRect);
        break;
    case 'c':
        SDL_BlitSurface(considerable, 0, screen, &blockRect);
        break;
    default:
        // do nothing
        ;
    }

    SDL_UpdateRect(screen, blockRect.x, blockRect.y, blockRect.w, blockRect.h);
}
void drawAll() {
    drawBoard();
    for(int i=0;i<15;++i) {
        for(int j=0;j<15;++j) {
            drawPiece(get(i,j),j,i);
        }
    }
}

void check(Pos p) {
    namespace b=board;
    uint8_t buf[sizeof(b::mark)];
    markThreats();
    memcpy(buf, b::mark, sizeof(b::mark));
    updateLines(p);
    if(!memcmp(buf, b::mark, sizeof(b::mark))) {
        cout<<"Passed"<<endl;
    } else {
        cout<<"Failed"<<endl;
    }
}

int gameLoop() {
    SDL_Event event;
    Pos p,last(15,0);
    bool busy=false;

    while ( SDL_WaitEvent(&event) >= 0 ) {
        switch (event.type) {
        case SDL_MOUSEBUTTONDOWN: 
            if( event.button.button == SDL_BUTTON_LEFT ) {
                if(busy)
                    continue;
                if(last.row!=15)
                    drawPiece(X,last.col,last.row);
                p=Pos((event.button.y)/25, (event.button.x)/25);
                if(get(p.row,p.col))
                    continue;
                last=p;
                board::i8Steps[board::ply][0]=p.row;
                board::i8Steps[board::ply][1]=p.col;
                set(last.row, last.col, X);
#ifdef DEBUG_GOMOKU
                cout<<"["<<(int)p.col<<", "<<(int)p.row<<"]\n";
#endif
                drawPiece(O,last.col,last.row);
                drawPiece('.',last.col,last.row);
                busy=true;
                p=move();
                drawPiece(O,last.col,last.row);
                drawPiece(X,p.col,p.row);
                drawPiece('.',p.col,p.row);
                last=p;
                busy=false;
            }
        break;

        case SDL_KEYDOWN:
            switch(event.key.keysym.sym) {
            case SDLK_SPACE:
                if(board::ply==0) {
                    // initEverything();
                    last=move();
                } else {
                    initEverything();
                    last=Pos(15,0);
                }
                busy=false;
                drawBoard();
                drawPiece(X,last.col,last.row);
                break;
            case SDLK_r:
                initEverything();
                last=Pos(15,0);
                busy=false;
                drawBoard();
                break;
            case SDLK_BACKSPACE:
                break;
                // TODO
                if(board::ply>0) {
                    p=board::steps[--board::ply];
                    unset(p.row, p.col, get(p.row, p.col));
                }
                if(board::ply>0) {
                    p=board::steps[--board::ply];
                    unset(p.row, p.col, get(p.row, p.col));
                }
                drawAll();
                break;
            case SDLK_c:
                check(last);
                break;
            case SDLK_q:
                return 0;
            default:
                break;
            }
            break;

        case SDL_QUIT: {
            return 0;
        }
        break;
        default:
        break;
        }
    }
    return 0;
}

int main(int argc,char** argv) {
    if(SDL_Init(SDL_INIT_VIDEO)==-1) {
        return -1;
    } else {
        SDL_WM_SetCaption("GoMoku test", "icon");
        SDL_WM_SetIcon(SDL_LoadBMP("bmp/icon.bmp"),0);
        //cout<<"HI!"<<endl;
    }


    // benchmark
#if 0
    set(7,7,O);
    set(7,8,X);
    set(8,8,O);
    set(7,6,X);
    set(6,6,O);
    set(5,5,X);
    set(6,7,O);
    set(9,8,X);
    set(4,7,O);
    clock_t begin=clock();
    for(int i=0;i<1000000;++i) {
        markThreats();
    }
    cout<<"markThreats() x 1000000 : "<<clock()-begin<<" clocks"<<endl;
    begin=clock();
    for(int i=0;i<1000000;++i) {
        updateLines(Pos(4,8));
    }
    cout<<"updateLines(Pos(4,8)) x 1000000 : "<<clock()-begin<<" clocks"<<endl;
#endif

    srand(time(0));
    screen = SDL_SetVideoMode( 376, 376, 0, SDL_SWSURFACE|SDL_DOUBLEBUF );
    SDL_SetCursor(cursor());
    SDL_ShowCursor(SDL_ENABLE);
    atexit(SDL_Quit);
    boardImg = SDL_LoadBMP("bmp/board.bmp");
    black = SDL_LoadBMP("bmp/black.bmp");
    white = SDL_LoadBMP("bmp/white.bmp");
    threat= SDL_LoadBMP("bmp/threat.bmp");
    considerable=SDL_LoadBMP("bmp/considerable.bmp");
    available=SDL_LoadBMP("bmp/available.bmp");

    SDL_SetColorKey(black, SDL_SRCCOLORKEY, SDL_MapRGB(black->format, 255, 0, 255) );
    SDL_SetColorKey(white, SDL_SRCCOLORKEY, SDL_MapRGB(white->format, 255, 0, 255) );
    SDL_SetColorKey(threat, SDL_SRCCOLORKEY, SDL_MapRGB(threat->format, 255, 0, 255) );
    SDL_SetColorKey(considerable, SDL_SRCCOLORKEY, SDL_MapRGB(considerable->format, 255,0,255));
    SDL_SetColorKey(available, SDL_SRCCOLORKEY, SDL_MapRGB(available->format, 255,0,255));

    if(boardImg == 0) {
        cerr<<"WTF"<<endl;
    }
    drawBoard();

    return gameLoop();
}

// {{{ cursor
static const char *arrow[] = {
  /* width height num_colors chars_per_pixel */
  "    32    32        3            1",
  /* colors */
  "X c #000000",
  ". c #ffffff",
  "  c None",
  /* pixels */
  "X                               ",
  "XX                              ",
  "X.X                             ",
  "X..X                            ",
  "X...X                           ",
  "X....X                          ",
  "X.....X                         ",
  "X......X                        ",
  "X.......X                       ",
  "X........X                      ",
  "X.....XXXXX                     ",
  "X..X..X                         ",
  "X.X X..X                        ",
  "XX  X..X                        ",
  "X    X..X                       ",
  "     X..X                       ",
  "      X..X                      ",
  "      X..X                      ",
  "       XX                       ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "0,0"
};

static SDL_Cursor *cursor()
{
  int i, row, col;
  Uint8 data[4*32];
  Uint8 mask[4*32];
  int hot_x, hot_y;

  i = -1;
  for ( row=0; row<32; ++row ) {
    for ( col=0; col<32; ++col ) {
      if ( col % 8 ) {
        data[i] <<= 1;
        mask[i] <<= 1;
      } else {
        ++i;
        data[i] = mask[i] = 0;
      }
      switch (arrow[4+row][col]) {
        case X:
          data[i] |= 0x01;
          mask[i] |= 0x01;
          break;
        case '.':
          mask[i] |= 0x01;
          break;
        case ' ':
          break;
      }
    }
  }
  sscanf(arrow[4+row], "%d,%d", &hot_x, &hot_y);
  return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
}

// }}}
